<template>
  <TableDivBox :data="data" @searchBtn="searchBtn" @resetForm="resetForm" :margin="margin">
    <template #search="{ search }" v-if="($slots.search || dataInfo.searchThead.length > 0) && !data.isNotSearch">
      <ElFormItemBox label="" prop="likeWords" v-if="dataInfo?.searchThead?.length > 0">
        <template #label>
          <template v-if="dataInfo.searchThead.length > 1">
            <el-dropdown placement="bottom-start">
              <span class="flex-start-center">
                <span class="text-overflow-1" :style="{
                  maxWidth: '90px'
                }">
                  {{ proxy.$arrFind(dataInfo.searchThead, search.queryDataBaseFiled)?.label || '关键字段' }}
                </span>
                <el-icon><arrow-down /></el-icon>
              </span>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item v-for="item in dataInfo.searchThead" @click="() => {
                    search.queryDataBaseFiled = item.value
                    search.likeWords = ''
                  }" :key="item.value">{{ item.label }}</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </template>
          <p v-else>
            {{ proxy.$arrFind(dataInfo.searchThead, search.queryDataBaseFiled)?.label || '关键字段' }}
          </p>
        </template>
        <ElInputBox :data="search" dataName="likeWords"
          :placeholder="`请输入${proxy.$arrFind(dataInfo.searchThead, search.queryDataBaseFiled)?.label}`" />
      </ElFormItemBox>
      <slot name="search" :search="search" />
    </template>
    <template #headL v-if="data.title || title">
      <h3>{{ data.title || title }}</h3>
      <el-popover class="box-item" :width="600" :visible="dataInfo.theadShow" placement="right-start"
        v-if="data.theadCode">
        <template #reference>
          <el-icon @click="dataInfo.theadShow = !dataInfo.theadShow">
            <Setting />
          </el-icon>
        </template>
        <div class="p-12 list-b-12">
          <div class="flex-between-center popover-head">
            <h3>表头设置</h3>
            <div class="list-r-8">
              <el-button type="" size="small" @click="() => {
                dataInfo.theadShow = false
              }">取消</el-button>
              <el-button type="primary" size="small" @click="() => {
                saveHeader()
                dataInfo.theadShow = false
              }">保存</el-button>
            </div>
          </div>
          <TableBoxMx :data="{
            tableId: 'tableThead',
            maxHeight: '500',
            tbody: dataInfo.thead,
            sortKey: 'columnSort', //排序key
            thead: [
              {
                label: '标题',
                prop: 'columnName',
                align: 'left',
                width: null,
              },
              {
                label: '宽度',
                prop: 'columnWidth',
                align: 'center',
                width: 160,
                formType: 'number',
              },
              {
                label: '浮动',
                prop: 'isFloat',
                align: 'center',
                width: 80,
                formType: 'switch',
              },
              {
                label: '显示',
                prop: 'visible',
                align: 'center',
                width: 80,
                formType: 'switch'
              },
            ],
          }">
          </TableBoxMx>
        </div>
      </el-popover>
      <el-icon @click="searchBtn">
        <Refresh />
      </el-icon>
      <div class="list-r-8" v-if="(data?.operation?.length > 0 && dataInfo.row) && (!isRadio || isShowBtn)">
        <template v-for="btn in data?.operation">
          <template v-if="btn.children?.length > 0">
            <el-dropdown
              v-if="btn.children?.find((el: any) => !!!(typeof el.disabled === 'function' ? el.disabled(dataInfo.row) : el.disabled))">
              <el-button type="primary"
                :disabled="typeof btn.disabled === 'function' ? btn.disabled(dataInfo.row) : false">
                {{ typeof btn.title === 'function' ? btn.title(dataInfo.row) : btn.title }}<el-icon
                  class="el-icon--right"><arrow-down /></el-icon>
              </el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <template v-for="child in btn.children">
                    <el-dropdown-item
                      :disabled="typeof child.disabled === 'function' ? child.disabled(dataInfo.row) : false"
                      @click="child.click(dataInfo.row)">
                      {{ typeof child.title === 'function' ? child.title(dataInfo.row) : child.title }}
                    </el-dropdown-item>
                  </template>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </template>
          <template v-else>
            <el-button type="primary" @click="btn.click(dataInfo.row)"
              v-if="!!!(typeof btn.hidden === 'function' ? btn.hidden(dataInfo.row) : btn.hidden) && !!!(typeof btn.disabled === 'function' ? btn.disabled(dataInfo.row) : false)">
              {{ typeof btn.title === 'function' ? btn.title(dataInfo.row) : btn.title }}
            </el-button>
          </template>
        </template>
      </div>
      <div class="flex-start-center list-r-8" v-if="data.sort && data.sort.length > 0">
        <template v-for="(item, index) in data.sort">
          <el-divider direction="vertical" v-if="index !== 0" />
          <div class="sortItem" :class="{
            on: item.value === data.search?.orderByFiled
          }" @click="() => {
            if (data.search.orderByFiled !== item.value) {
              data.search.orderByType = 0
              data.search.orderByFiled = item.value
            } else {
              data.search.orderByType = data.search.orderByType === 0 ? 1 : 0
            }
            searchBtn()
          }">
            <p>{{ item.label }}</p>
            <div class="sortItem-operation">
              <el-icon :class="{
                'text-color-primary': item.value === data.search?.orderByFiled && data.search?.orderByType === 1
              }">
                <CaretTop />
              </el-icon>
              <el-icon :class="{
                'text-color-primary': item.value === data.search?.orderByFiled && data.search?.orderByType === 0
              }">
                <CaretBottom />
              </el-icon>
            </div>
          </div>
        </template>
      </div>
      <slot name="headL" :search="data?.search"></slot>
    </template>
    <template #headR v-if="((data.btns?.length > 0) || $slots.headR) && (!isRadio || isShowBtn)">
      <template v-for="btn in data.btns">
        <el-dropdown v-if="btn.children && btn.children.length > 0" placement="bottom-end" size="default">
          <el-button :type="btn.type">
            {{ btn.title }}<el-icon class="el-icon--right"><arrow-down /></el-icon>
          </el-button>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item v-for="child in btn.children" @click.stop="
                () => {
                  if (child.click && typeof child.click === 'function') {
                    child.click(data.checkbox.list);
                  }
                }
              ">{{ child.title }}</el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
        <div v-else-if="btn.title === '扫码'">
          <el-input class="w260" v-model.trim="btn.value" :placeholder="btn.placeholder || '请扫码或输入生产单号'" clearable
            @change="btn.click(btn)">
            <template #prefix>
              <i class="iconfont icon-scanning"></i>
            </template>
            <template #append>
              <el-icon @click.stop="btn.click(btn)">
                <Search />
              </el-icon>
            </template>
          </el-input>
        </div>
        <el-popover :width="300" trigger="click" placement="bottom-end" v-else-if="btn.icon === 'Upload'">
          <template #reference>
            <el-button :icon="btn.icon" :type="btn.type">
              {{ btn.title }}
            </el-button>
          </template>
          <div class="p-12 list-b-12 text-center">
            <ElUploadBox drag :accept="btn.accept" @changeBtn="btn.click" />
            <el-link type="primary" @click="proxy.$downloadFile(btn.download.name, 'xlsx')"
              v-if="btn.download">点击下载模版</el-link>
          </div>
        </el-popover>
        <el-button :type="btn.type" :icon="btn.icon" size="default"
          :disabled="typeof btn.disabled === 'function' ? btn.disabled(data.checkbox?.list) : btn.disabled" @click="
            () => {
              if (btn.click && typeof btn.click === 'function') {
                btn.click(data.checkbox?.list);
              }
            }
          " v-permission="btn.permission" v-else>
          {{ btn.title }}
        </el-button>
      </template>
      <slot name="headR" v-if="$slots.headR" />
    </template>
    <template #default>
      <el-auto-resizer class="full">
        <template #default="{ height, width }">
          <ElTableBox :tbodyList="data?.tbodyList" :selectArr="data?.selectArr" :height="height" :width="width"
            :tbody="data?.tbody" :thead="data?.thead" :selectable="selectable || data?.checkbox?.selectable"
            :loading="loading || data.loading" :rowKey="data?.rowKey"
            :spanMethod="!!data.isColumn ? setSpanMethod : data?.spanMethod" :search="data?.search"
            :summary="data?.summary" isHighlight @handleSelectionChange="handleSelectionChange"
            @headerDragend="headerDragend" @rowClick="rowClick" @dblclick="dblclick" @searchBtn="searchBtn"
            @tableRadioBtn="tableRadioBtn" @tableCheckboxBtn="tableCheckboxBtn" @cellClick="cellClick"
            @toggleSelection="toggleSelection" :isRadio="isRadio" :isCheckbox="isCheckbox">
            <template #[key]="{ row, index }" v-for="(slot, key) in $slots" :key="key">
              <slot :name="key" :row="row" :index="index" v-if="!keyNotArr.includes(key)" />
            </template>
            <template #operation="{ row, index }" v-if="data?.operation?.length > 0 && (!isRadio || isShowBtn)">
              <template v-if="data.operation.length > 1">
                <el-dropdown size="small">
                  <el-link type="primary">
                    <span>操作</span>
                    <el-icon>
                      <ArrowDown />
                    </el-icon>
                  </el-link>
                  <template #dropdown>
                    <ElDropdownMenuBox :row="row" :index="index" :data="data.operation" />
                  </template>
                </el-dropdown>
              </template>
              <template v-else>
                <template v-for="btn in data.operation">
                  <el-link type="primary" @click.stop="btn.click(row)" v-if="
                    typeof btn.hidden === 'function' ?
                      btn.hidden(row) :
                      !btn.hidden">{{
                        typeof btn.title === 'function' ?
                          btn.title(row) :
                          btn.title
                      }}</el-link>
                </template>
              </template>
            </template>
          </ElTableBox>
        </template>
      </el-auto-resizer>
    </template>
  </TableDivBox>
</template>
<script setup lang="ts">
//获取pinia
// import { useUserStore } from '@/store/index';
// const userStores: any = useUserStore();
//获取当前实例
import { getCurrentInstance, onMounted, ref } from 'vue';
const { proxy } = getCurrentInstance() as any;
//获取父级数据
const props = withDefaults(
  defineProps<{
    data?: any; //主数据
    title?: string; //标题
    height?: number; //高度
    margin?: number; //间距
    isShowBtn?: boolean; //显示操作按钮
    isRadio?: boolean; //单选
    isCheckbox?: boolean; //单选
    loading?: boolean; //单选
    loadingMsg?: string; //单选
    selectable?: Function; //多选是否禁用
  }>(),
  {
  },
);
const keyNotArr: any = ref(['search', 'header']);
const dataInfo: any = reactive({
  theadShow: false,
  search: null,
  thead: [],
  searchThead: props.data.searchThead || [],
  row: null,
});
watch(() => props.data.tbody, (newVal, oldVal) => {
  if (newVal !== oldVal) {
    dataInfo.row = null
  }
  //是否存在合并的key
  if (!!props.data?.columnKey && props.data.tbody) {
    setMerge(props.data.tbody, props.data.columnKey)
  }
});
const emit = defineEmits<{
  //fn为父组件引入子组件是定义的子组件事件属性，可随意定义
  (event: 'searchBtn'): void;
  (event: 'resetForm'): void;
  (event: 'tableRadioBtn', row: any): void;
  (event: 'tableCheckboxBtn', arr: any): void;
}>();
const searchBtn = () => {
  dataInfo.row = null
  emit('searchBtn');
};
const resetForm = () => {
  emit('resetForm');
};
//设置合并数据
const setSpanMethod = (res: any) => {
  const { row, column } = res
  let isColumn = props.data.isColumn.includes(column.property);//需要合并的表头
  if (isColumn && row.rowspan >= 0) {
    // const _text = `${column.property}：${row[column.property]},[行：${row.rowIndex},列：${columnIndex},合并：${row.rowspan}]`;
    if (row.rowspan === 0) {
      return {
        rowspan: 0,
        colspan: 0,
      };
    } else {
      return {
        rowspan: row.rowspan,
        colspan: 1,
      };
    }
  } else {
    return {
      rowspan: 1,
      colspan: 1,
    };
  }
};
//设置合并数据
const setMerge = (arr: any, key: string) => {
  if (arr.length === 0) return
  let _rowspan = 1//合并数
  let _rowIndex = 0//合并数
  let _columnKey = ''//型号唯一编号
  arr.forEach((el: any, elIndex: number) => {
    if (_columnKey === el[key]) {
      el.rowspan = 0
      _rowspan++
    } else {
      _columnKey = el[props.data.columnKey]
      _rowIndex = elIndex
      _rowspan = 1
      el.rowspan = 1
    }
    arr[_rowIndex].rowspan = _rowspan//设置
  })
};
//单击某个单元格
const cellClick = (key: string, value: any) => {
  const _canSearchArr = dataInfo.searchThead.map((el: any) => el.value)
  const _search = props.data.search
  if (_canSearchArr.includes(key) && _search.queryDataBaseFiled !== key) {
    _search.queryDataBaseFiled = key
    _search.likeWords = ''
  }
};
//单击
const rowClick = (row: any) => {
  dataInfo.row = row
};
//双击
const dblclick = (row: any) => {
  const _operation = props.data.operation
  if (_operation?.length > 0) {
    const _row = _operation.find((el: any) => typeof el.hidden === 'function' ? !el.hidden(row) : !el.hidden)
    if (_row) {
      _row.click(row)
    }
  }
};
//多选数据
const toggleSelection = () => {
  props.data.selectArr = []
};
//多选数据
const tableCheckboxBtn = (arr: any) => {
  props.data.selectArr = []
  emit('tableCheckboxBtn', arr);
};
//单选数据
const tableRadioBtn = (row: any) => {
  emit('tableRadioBtn', row);
};
//更改表头
const headerDragend = (key: string, newWidth: number) => {
  setheaderWidth(dataInfo.thead, key, newWidth);
};
//更改表头
const setheaderWidth = (arr: any, key: string, newWidth: number) => {
  if (arr && arr.length > 0) {
    arr.forEach((el: any) => {
      if (el.columnCode === key) {
        el.columnWidth = newWidth;
        saveHeader();
        return;
      } else {
        setheaderWidth(el.children, key, newWidth);
      }
    });
  }
};
const getHeader = () => {
  if (props.data.theadCode) {
    proxy.$api.Public.GetPageTableStyleDataList({
      tableCode: props.data.theadCode,
    })
      .then((res: any) => {
        let _thead = res.sort((itemA: any, itemB: any) => itemA.columnSort - itemB.columnSort);
        const _theadHidden = proxy.data.theadHidden
        _thead = _thead.filter((el: any) => el.columnCode)
        if (_theadHidden && _theadHidden.length > 0) {
          _thead = _thead.filter((el: any) => !_theadHidden.includes(el.columnCode))
        }
        dataInfo.thead = _thead.map((el: any) => ({
          ...el,
          columnWidth: setHeaderWidth(el.columnWidth),
        }));
        props.data.thead = _thead.map((el: any) => ({
          label: el.columnName,
          prop: el.columnCode,
          hidden: !el.visible,
          align: setHeaderObj(el).align,
          tooltip: setHeaderObj(el).tooltip,
          width: setHeaderObj(el).width,
          fixed: setHeaderObj(el).fixed,
          isCanSearch: el.isCanSearch,
        }));
        _setearchThead(props.data.thead)
      })
      .catch(() => { });
  } else {
    _setearchThead()
  }
  function _setearchThead(thead: any = props.data?.thead || []) {
    const newSearchThead = JSON.parse(JSON.stringify(thead)).filter((el: any) => el.isCanSearch).map((el: any) => ({
      label: el.label,
      value: el.prop,
    })) || []
    dataInfo.searchThead = newSearchThead.concat(props.data.searchThead || [])

    let _search = props.data.search
    if (_search && dataInfo.searchThead.length > 0 && !!!props.data.search.queryDataBaseFiled) {
      const _row: any = dataInfo.searchThead[0]
      _search.queryDataBaseFiled = _row.value
    }
  }
};
//设置表头宽度
const setHeaderWidth = (width: string | number | null) => {
  if (width && Number(width) > 0) {
    return Number(Number(width).toFixed(0));
  } else {
    return null;
  }
};
//保持表头
const saveHeader = () => {
  let _data = dataInfo.thead.map((el: any) => ({
    ...el,
    columnWidth: el.columnWidth || '',
  }));
  proxy.$api.Public.SaveOperatorPageTableStyle(_data)
    .then(() => {
      ElMessage({
        message: '表头保存成功',
        type: 'success',
      });
      getHeader();
    })
    .catch(() => { });
};
const setHeaderSort = (arr: any, fromIndex: any, toIndex: any) => {
  // 检查索引是否有效
  if (fromIndex < 0 || fromIndex >= arr.length || toIndex < 0 || toIndex > arr.length) {
    console.error('无效的索引');
    return;
  }
  // 使用 splice 方法取出要移动的元素
  const [element] = arr.splice(fromIndex, 1);
  // 在新位置插入该元素
  arr.splice(toIndex - 1, 0, element);
  arr = arr.map((el: any, index: number) => (el.columnSort = index + 1));
};
const setHeaderObj = (row: any) => {
  let _obj: any = {
    align: 'left',
    width: null,
    tooltip: false,
    fixed: !!row.isFloat,
  };
  if (row.columnWidth && !row.columnName.includes('备注')) {
    _obj.width = setHeaderWidth(row.columnWidth);
  }
  if (row.columnName.includes('状态') || row.columnName.includes('编码') || row.columnName.includes('编号') || row.columnName.includes('排序号')) {
    _obj.align = 'center';
  }
  return _obj;
};
const copySearch = () => {
  if (!dataInfo.search && props.data.search) {
    dataInfo.search = JSON.parse(JSON.stringify(props.data.search));
  }
};
//取整数
const handleInput = (row: any, key: string, value: any) => {
  // 正则表达式匹配仅包含整数（包括负数）的字符串
  const regex = /^-?\d*$/;

  // 检查输入是否符合整数规则
  if (regex.test(value)) {
    // 如果输入有效，则更新columnWidth
    row[key] = value;
  } else {
    // 如果输入无效，撤销此次输入
    // Vue会自动忽略不符合正则的输入，这里主要是为了演示如何处理

    // 可选：进一步处理，比如移除所有非数字字符保留负号
    row[key] = value.replace(/[^-\d]/g, '');
  }
};
//多选
const handleSelectionChange = (arr: any[]) => { };
//跨页监听回调
import { listenMsg } from '@/utils/crossTagMag';
//多选

onMounted(() => {
  copySearch();
  getHeader();
  listenMsg(searchBtn);
});
</script>
<style scoped lang="scss">
.tableBox {
  --m: 8px;
  display: flex;
  flex-direction: column;

  >* {
    background: $white;

    &:not(:last-child) {
      margin-bottom: var(--m);
    }
  }

  .tableBox-search {
    padding: var(--m);
  }

  .tableBox-header {
    padding: var(--m);
    display: flex;
    align-items: center;
    justify-content: space-between;

    >* {
      display: flex;
      align-items: center;

      &:not(:last-child) {
        margin-right: var(--m);
      }

      >* {
        &:not(:last-child) {
          margin-right: var(--m);
        }
      }
    }
  }

  .tableBox-main {
    flex: 1;
    overflow: hidden;
    display: flex;
    flex-direction: column;

    .tableBox-tbody {
      flex: 1;
      overflow: hidden;
      margin: -1px;
      position: relative;
    }

    .tableBox-pagination {
      padding: var(--m);
    }
  }
}

.sortItem {
  display: flex;
  align-items: center;
  cursor: pointer;

  &.on {
    color: $primary;
  }

  .sortItem-operation {
    display: flex;
    flex-direction: column;
    margin-left: 2px;

    >* {
      font-size: 12px;
      color: $info;

      &:not(:last-child) {
        margin-bottom: -6px;
      }
    }
  }
}
</style>
